home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
UTILITY
/
CMDED2E6.ARJ
/
DIRS.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-06-30
|
13KB
|
558 lines
; DIRS.ASM
; (c) 1989, 1990 Ashok P. Nadkarni
;
;This module implements the directory stack feature of the cmdedit program.
INCLUDE ascii.inc
INCLUDE common.inc
INCLUDE general.inc
INCLUDE buffers.inc
INCLUDE dos.inc
INCLUDE bios.inc
PUBLIC dirs_init
PUBLIC execute_popd
PUBLIC execute_pushd
PUBLIC execute_chd
PUBLIC execute_rstdir
PUBLIC execute_dirstat ;added by wd
PUBLIC execute_backdir ;added by wd
PUBLIC enable_dircmds
PATHBUF_SIZE EQU 68
CSEG SEGMENT PARA PUBLIC 'CODE'
EXTRN user_command:BYTE
EXTRN in_appl:BYTE
EXTRN linebuf:BYTE ;line buffer
EXTRN backbuf:BYTE ;back-dir buffer - added by wd
EXTRN lastchar:WORD
EXTRN dirstk_error:BYTE
EXTRN resident:BYTE
EXTRN abort_install:PROC
EXTRN abort_processing:PROC
EXTRN skip_whitespace:PROC
EXTRN skip_nonwhite:PROC
EXTRN tolower:PROC
dir_stk $string_stack <> ;Buffer descriptors
enable_dircmds db 1 ;If 1, enables directory commands
; even if caller is not DOS
DGROUP GROUP CSEG
ASSUME CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP
;+
; FUNCTION : dirs_init
;
; Initializes the various data structures associated with the
; directory stack buffer. CALLER MUST ENSURE PASSED ADDRESSES ARE VALID
; AND BUFFER IS LARGE ENOUGH.
;
; Parameters:
; AX - length of buffer in bytes
; BX - address of buffer
;
; Returns:
; AX = 0 if no errors
; -1 otherwise
; Registers destroyed : BX
;-
dirs_init proc near
push bx
mov bx,offset DGROUP:dir_stk ;bx := address of buffer descriptors
xchg ax,cx ;CX = buffer size
pop ax ;AX = Buffer address
;BX points to appropriate descriptor
call near ptr strstk_init ;Initialize buffer and descriptor
ret
dirs_init endp
;+
; FUNCTION: execute_rstdir
;
; Called to reset the directory stack.
;
; Parameters:
; None.
;-
execute_rstdir proc near
mov bx,offset DGROUP:dir_stk
call near ptr strstk_reset
ret
execute_rstdir endp
;+
; FUNCTION : dir_push
;
; Called to push a drive and path onto the directory stack. The
; string must end in a 0 byte.
;
; Parameters:
; DX ->string to push
;
; Returns:
; CF = 1 if errors
; 0 no errors
;
; Register(s) destroyed:
; AX,BX,CX,DX
;-
dir_push proc near
@save di
mov di,dx ;di->string
mov cx,0ffffh
xor al,al
repne scasb
mov ax,cx
not ax ;AX<-length of string
; including null terminator
mov bx,offset DGROUP:dir_stk
xor cx,cx ;Don't force push
call near ptr strstk_push ;Params AX,BX,CX,DX
; strstk_push sets/resets CF
@restore
ret
dir_push endp
;+
; FUNCTION : abort_dir_op
;
; Called to abort a directory stack operation. Action taken
; depends on whether the program is already resident or is being
; installed. This routine does NOT return to caller.
;
; Parameters:
; AX = code to pass to abort_processing
;
; Returns:
; Nothing.
; Register(s) destroyed:
;-
abort_dir_op proc near
mov dx,offset DGROUP:abort_processing
cmp resident,0
jne @abort_dir_op_90 ;Jump if resident
@DispStr dirstk_error
mov dx,offset DGROUP:abort_install
@abort_dir_op_90:
jmp dx
abort_dir_op endp
;+
; FUNCTION : check_dircmd_allowed
;
; Makes sure DOS is the caller or directory commands have been
; enabled for all applications and returns. Else aborts.
;
; Parameters:
; None.
;
; Returns:
; Nothing.
; Register(s) destroyed:
; AX
;-
check_dircmd_allowed proc near
cmp enable_dircmds,1
je @check_dircmd_allowed_99
mov ax,E_DIRSTK_DOS ;Assume error
cmp in_appl,1 ;In application ?
je abort_dir_op ;Yes, abort
@check_dircmd_allowed_99: ;Else return
ret
check_dircmd_allowed endp
;+
; FUNCTION : save_drv_path
;
; Saves the current drive and path in the specified buffer in the
; form `D:\dir1....' where the current drive letter. The buffer
; MUST be long enough.
;
; Parameters:
; AX = address of save buffer
;
; Returns:
; Nothing.
;
; Register(s) destroyed:
; AX,DX
;-
save_drv_path proc near
@save si,di
mov di,ax ;DI->save buffer
@GetDrv ;AL<-drive number
add al,'A' ;AL<-drive letter. wd changed 'a' to 'A'
stosb ;Remember current drive
mov al,':'
stosb
mov al,'\'
stosb
@GetDir di ;Remember current path
@restore
ret
save_drv_path endp
;+
; FUNCTION : change_drv_path
;
; Changes the current drive and directory to the one specified.
;
; Parameters:
; AX ->path in the form `D:\dir1\dir2\...' terminated
; with a 0 byte where D is the drive letter. Entire
; path name need no be given. It is OK if the last
; directory in the path is followed by a '\' or a '/'.
;
; Returns:
; CF = 0 if current drive and directory succesfully changed,
; 1 if any errors (drive and path both unchanged)
; Register(s) destroyed:
;-
change_drv_path proc near
@save si,di
push bp
mov bp,sp
sub sp,PATHBUF_SIZE
cur_path equ <byte ptr [bp-PATHBUF_SIZE]>
push ax ;Remember new path
lea ax,cur_path ;AX->current path save buf
call near ptr save_drv_path ;Save current disk/dir
pop dx ;DX->new path
mov si,dx ;SI->new path
mov di,dx
xor al,al ;Search for terminator
mov cx,0ffffh
repne scasb ;DI->byte after NULL
mov ah,[di-2] ;AL=byte before NULL
cmp ah,'\' ;Extra '\' char ?
je @change_drv_path_5 ;Yes
cmp ah,'/' ;Extra '/' char ?
jne @change_drv_path_10 ;No
@change_drv_path_5:
;If '\' at the end, make sure it is not of the form d:\ or just \
cmp byte ptr [di-3],':'
je @change_drv_path_10
dec di
dec di ;DI->'\' character
cmp di,dx ;Solitary '\' ?
je @change_drv_path_10 ;Yes
mov [di],al ;No, replace '\' with 0
@change_drv_path_10:
@ChDir dx
jnc @change_drv_path_80 ;No error
; Check if error was because drive was specified but not the path.
; In this case, we should only change the drive.
cmp byte ptr 2[si],0 ;third byte nust be null
jne @change_drv_path_85 ;Nope
cmp byte ptr 1[si],':' ;Drive specified ?
jne @change_drv_path_85 ;Nope
jmp short @change_drv_path_82
@change_drv_path_80:
cmp byte ptr 1[si],':' ;Drive spec ?
clc ;To indicate success
jne @change_drv_path_99 ;No, all done
@change_drv_path_82:
lodsb ;AL<-drive
call near ptr tolower
sub al,'a' ;AL<-drive number
@SetDrv al ;Change the drive
jnc @change_drv_path_99 ;No error
; Error, restore path, drive would not have been changed
@change_drv_path_85:
lea dx,cur_path
@ChDir dx
stc ;Indicate error to caller
@change_drv_path_99:
mov sp,bp
pop bp
@restore
ret
change_drv_path endp
;+
; FUNCTION : execute_backdir by wd
;
; Go to the previously visited directory.
;
; Parameters:
; None.
;
; Returns:
; Nothing.
;
; Register(s) destroyed:
; AX,BX,CX,DX
;-
execute_backdir proc near
call near ptr check_dircmd_allowed
lea bx,backbuf
cmp byte ptr [bx],0
je @execute_backdir_99
mov dx,bx
call near ptr dir_push
xor cx,cx
jmp short execute_popd
@execute_backdir_99:
ret
execute_backdir endp
;+
; FUNCTION : execute_popd
;
; Pops the topmost element off the directory stack and makes it
; the current drive/directory.
;
; Parameters:
; None.
;
; Returns:
; Nothing.
;
; Register(s) destroyed:
; AX,BX,CX,DX
;-
execute_popd proc near
call near ptr check_dircmd_allowed
@save si,di
push bp
mov bp,sp
sub sp,PATHBUF_SIZE
topdir equ PATHBUF_SIZE
lea ax,backbuf ;this and next line added by wd
call near ptr save_drv_path
mov bx,offset DGROUP:dir_stk ;BX->dir stack descriptor
call near ptr strstk_settop
lea ax,[bp-topdir]
mov cx,PATHBUF_SIZE
call near ptr strstk_copy ;Get top of stack
; String is terminated
; by a 0 byte
jc @execute_popd_90
or ax,ax ;Empty stack ?
jz @execute_popd_90 ;Yes, error
lea ax,[bp-topdir] ;AX->new path
call near ptr change_drv_path ;Change drive and path
jc @execute_popd_90
call near ptr strstk_kill ;Delete top of stack
mov sp,bp
pop bp
@restore
; Klugery - return a zero length string to DOS in order to set prompt properly.
mov lastchar,offset DGROUP:linebuf
mov user_command,1 ;indicate line to be
; returned to DOS
ret
@execute_popd_90:
mov ax,E_DIRSTK_EMPTY
jmp near ptr abort_dir_op
execute_popd endp
;+
; FUNCTION : execute_pushd
;
; If a parameter is given, pushes current directory/disk onto the
; dir stack and changes to the parameter. If no parameter,
; exchange the top of directory stack with current disk-directory.
;
; Parameters:
; SI -> first char in linebuf following this command
; CX = remaining num chars in line
;
; Returns:
; Nothing.
;
; Register(s) destroyed:
; AX,BX,CX,DX
;-
execute_pushd proc near
@save si,di
push bp
mov bp,sp
; sub sp,2*PATHBUF_SIZE
;cur_path equ <byte ptr [bp-PATHBUF_SIZE]>
;new_path equ <byte ptr [bp-(2*PATHBUF_SIZE)]>
;wd replaced above 3 lines by following 2 lines:
sub sp,PATHBUF_SIZE
new_path equ <byte ptr [bp-PATHBUF_SIZE]>
call near ptr check_dircmd_allowed
; Will return only if so
; push cx ;Save line length
; lea ax,cur_path
;wd replaced above 2 lines by following line:
lea ax,backbuf
call near ptr save_drv_path ;Save current drive and path
; pop cx ;CX<-restored line length (removed by wd)
call near ptr skip_whitespace
; SI->first non blank, CX<-num remaining chars
jcxz @execute_pushd_50 ;Exchange directory
; with top of stack
push si ;SI->path to change to
call near ptr skip_nonwhite
; SI->first non-blank
mov byte ptr [si],0 ;Terminating 0 byte
; We are guaranteed place for a 0 because of the dummy byte after linebuf
pop ax ;AX->dir to change to
call near ptr change_drv_path ;Change path and drive
jc @execute_pushd_32 ;Error
@execute_pushd_25:
; lea dx,cur_path ;changed to line below by wd
lea dx,backbuf
call near ptr dir_push ;Push onto stack
jnc @execute_pushd_100 ;No error
@execute_pushd_30:
; Error. Restore original directory and display error message.
; lea ax,cur_path ;changed to line below by wd
lea ax,backbuf
call near ptr change_drv_path
@execute_pushd_32:
mov ax,E_DIRSTK
jmp abort_dir_op
@execute_pushd_50:
; Exhange current directory with the directory at the top of the stack
mov bx,offset DGROUP:dir_stk ;BX->dir stack descriptor
call near ptr strstk_settop
lea ax,new_path
mov cx,PATHBUF_SIZE
call near ptr strstk_copy ;Get top of stack
; String is terminated
; by a 0 byte
jnc @execute_pushd_60
@execute_pushd_55:
; lea ax,cur_path ;changed to line below by wd
lea ax,backbuf
call near ptr change_drv_path
mov ax,E_DIRSTK_EMPTY
jmp abort_dir_op
@execute_pushd_60:
or ax,ax ;Empty stack ?
jz @execute_pushd_55 ;Yes, error
lea ax,new_path ;AX->new path
call near ptr change_drv_path ;Change drive and path
jc @execute_pushd_30
call near ptr strstk_kill ;Delete top of stack
; lea dx,cur_path ;changed to line below by wd
lea dx,backbuf
call near ptr dir_push
jnc @execute_pushd_100 ;All set
; Error. Restore original top of stack
lea dx,new_path
call near ptr dir_push ;Push must succeed
jmp short @execute_pushd_30
@execute_pushd_100:
mov sp,bp
pop bp
@restore
; Klugery - return a zero length string to DOS in order to set prompt properly.
mov lastchar,offset DGROUP:linebuf
mov user_command,1 ;indicate line to be
; returned to DOS
ret
execute_pushd endp
;+
; FUNCTION : execute_chd
;
; Changes to the disk and directory specified as parameter.
;
; Parameters:
; SI -> first char in linebuf following this command
; CX = remaining num chars in line
;
; Returns:
; Nothing.
;
; Register(s) destroyed:
; AX,BX,CX,DX
;-
execute_chd proc near
@save si,di
push bp
mov bp,sp
sub sp,PATHBUF_SIZE
new_path equ <byte ptr [bp-PATHBUF_SIZE]>
call near ptr check_dircmd_allowed
; Will return only if so
; push cx ;Save line length ;wd replaced by next 2 lines
lea ax,backbuf
call near ptr save_drv_path ;Save current drive and path
call near ptr skip_whitespace
; SI->first non blank, CX<-num remaining chars
jcxz @execute_chd_100 ;No args
; with top of stack
push si ;SI->path to change to
call near ptr skip_nonwhite
; SI->first non-blank
mov byte ptr [si],0 ;Terminating 0 byte
; We are guaranteed place for a 0 because of the dummy byte after linebuf
pop ax ;AX->dir to change to
call near ptr change_drv_path ;Change path and drive
jnc @execute_chd_100 ;No error
mov ax,E_DIRSTK
jmp abort_dir_op
@execute_chd_100:
mov sp,bp
pop bp
@restore
; Klugery - return a zero length string to DOS in order to set prompt properly.
mov lastchar,offset DGROUP:linebuf
mov user_command,1 ;indicate line to be
; returned to DOS
ret
execute_chd endp
;+
; FUNCTION : execute_dirstat by wd
;
; This function outputs the entire directory stack.
;
; Parameters:
; SI -> first char in linebuf following this command
; CX == remaining num chars in the line
;
; Returns:
; Nothing.
;
; Register(s) destroyed:
; AX,BX,CX,DX
;-
execute_dirstat proc near
mov bx,offset DGROUP:dir_stk ;BX->dir stack descriptor
call near ptr strstk_output
ret
execute_dirstat endp
CSEG ENDS
END